package com.jy.api.service.impl;

import com.jy.api.dao.*;
import com.jy.api.domain.*;
import com.jy.api.service.NumService;
import com.jy.api.signUpReq.admin.NumReq;
import com.jy.api.signUpReq.pos.NumDetailsRes;
import com.jy.api.signUpReq.pos.OneOpenNumRes;
import com.jy.api.signUpReq.pos.OpenNumReq;
import com.jy.api.util.JodaUtils;
import com.jy.api.util.Result;
import com.jy.api.util.StringSplitUtils;
import com.jy.api.util.TimeUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Time;
import java.util.*;

/**
 * Created by xiaohua on 2019/2/18.
 */
@Service
public class NumServiceImpl implements NumService {

    @Autowired
    private NumDao numDao;

    private SimpMessagingTemplate simpMessagingTemplate;
    @Autowired
    private PartitionDao partitionDao;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private BillRuleDao ruleDao;
    @Autowired
    private EmployeeDao employeeDao;
    @Autowired
    private NumTransactionDao transactionDao;
    @Autowired
    private BillRuleDao billRuleDao;

    @Autowired
    public void setSimpMessagingTemplate(SimpMessagingTemplate simpMessagingTemplate) {
        this.simpMessagingTemplate = simpMessagingTemplate;
    }


    @Override
    public Page<Num> getAllNumById(String id, Pageable pageable) {
        return numDao.findAllByStoreIdAndEnabled(id, true, pageable);
    }


    @Override
    @Transactional
    public Result updateNumById(NumReq req) {
        List<Num> list = numDao.findAllByPartitionIdAndEnabledOrderBySortDesc(req.getParId(), true);
        Partition partition = partitionDao.findOne(req.getParId());
        Num num = numDao.findOne(req.getNumId());
        for (Num n : list) {
            if (StringUtils.equals(n.getNumName(), req.getNumName())) {
                return new Result(400, "该桌号名字已存在，请核实后进行修改！");
            }
        }
        if (null != req.getNumName()) {
            num.setNumName(req.getNumName());
        } else {
            num.setSort(req.getSort());
        }
        num.setPeople(req.getPeople());
        num.setPartitionId(req.getParId());
        num.setParName(partition.getPartitionName());
        numDao.save(num);
        return new Result(200, "桌号修改成功");
    }

    @Override
    @Transactional
    public Result deleteNumById(NumReq req) {
        Num num = numDao.findOne(req.getNumId());
        num.setEnabled(false);
        return new Result(200, "删除成功");
    }

    @Override
    @Transactional
    public Result addNumById(NumReq req) {
        List<Num> list = numDao.findAllByPartitionIdAndEnabledOrderBySortDesc(req.getParId(), true);
        for (Num n : list) {
            if (StringUtils.equals(n.getNumName(), req.getNumName())) {
                return new Result(400, "该桌号名字已存在，请核实后进行修改！");
            }
        }
        Num num = new Num(req);
        numDao.save(num);
        return new Result(200, "桌号添加成功");
    }

    @Override
    public Result openNum(OpenNumReq req) {
        Num num = numDao.findOne(req.getNumId());
        if (!StringUtils.equals(num.getStatus().toString(), NumStatus.FREE.toString())) {
            return new Result(400, "该台已被预订/占用，请联系相关人员进行处理！");
        }
        if (StringUtils.equals(req.getSource(), NumStatus.BOOK.toString())) {
            num.setStatus(NumStatus.BOOK);
        } else {
            num.setStatus(NumStatus.BUSY);
        }
        NumTransaction transaction = new NumTransaction(req);
        double billRuleAmount = getBillRuleAmount(req, req.getBeginTime().toString(), new Date().toString());
        transaction.setRoomAmount(billRuleAmount);
        int min = TimeUtils.getMinTimeDifference(req.getBeginTime().toString(), new Date().toString());
        int hour=min / 60;
        int minute=min % 60;
        transaction.setInTime(hour+"小时"+minute+"分钟");
        transactionDao.save(transaction);
        numDao.save(num);
        com.jy.api.bean.Response response = new com.jy.api.bean.Response();
        response.setSource("BAR");
        response.setNumId(num.getId());
        response.setCount(1);
        simpMessagingTemplate.convertAndSend("/message/" + num.getStoreId(), response);
        return new Result(200, "开台/预订成功！");
    }

    @Override
    @Transactional
    public Result updateNum(OpenNumReq req) {
        Num num = numDao.findOne(req.getNumId());
        if (req.getType().equals("ON")) {
            if (!StringUtils.equals(num.getStatus().toString(), NumStatus.BUSY.toString())) {
                num.setStatus(NumStatus.BUSY);
            } else {
                return new Result(400, "该台已经是使用状态，请勿重复操作");
            }
        } else {
            List<Order> order = orderDao.findByNumIdAndStatusAndEnabledOrderByAddTimeDesc(num.getId(), OrderStatus.INIT, true);
            if (order.size() > 0) {
                return new Result(400, "该台还有订单未结账，请结账后再关闭台桌！");
            }
            num.setStatus(NumStatus.FREE);
        }
        numDao.save(num);
        com.jy.api.bean.Response response = new com.jy.api.bean.Response();
        response.setSource("BAR");
        response.setNumId(num.getId());
        response.setCount(1);
        simpMessagingTemplate.convertAndSend("/message/" + num.getStoreId(), response);

        return new Result(200, "设置成功！");
    }

    @Override
    public Map<String, Object> getOneNum(NumReq req) {
        Map<String, Object> map = new HashMap<>();
        List<Employee> employee = employeeDao.findByStoreIdAndEnabled(req.getStoreId(), true);
        List<OneOpenNumRes.EmpName> empNames = new ArrayList<>();
        List<OneOpenNumRes.Rules> rulesList = new ArrayList<>();
        Partition partition = partitionDao.findOne(req.getParId());
        OneOpenNumRes res = new OneOpenNumRes();
        Num num = numDao.findOne(req.getNumId());
        if (num.getStatus().equals(NumStatus.BUSY) || num.getStatus().equals(NumStatus.BOOK)) {
            map.put("result", new Result(400, "该台桌已被预订/占用"));
            map.put("data", null);
            return map;
        }
        res.setBeginTime(new Date());
        res.setNumName(num.getNumName());
        res.setParName(partition.getPartitionName());
        res.setPeople(num.getPeople());
        for (Employee e : employee) {
            OneOpenNumRes.EmpName empName = new OneOpenNumRes.EmpName();
            empName.setEmpId(e.getId());
            empName.setEmpName(e.getName());
            empName.setMobile(e.getUsername());
            empNames.add(empName);
        }
        res.setNames(empNames);
        List<Integer> s = StringSplitUtils.getString(partition.getRules());
        List<BillRule> billRule = ruleDao.findByIdInAndStoreIdAndEnabled(s, req.getStoreId(), true);
        for (BillRule rule : billRule) {
            OneOpenNumRes.Rules rules = new OneOpenNumRes.Rules();
            rules.setRuleId(rule.getId());
            rules.setRuleName(rule.getName());
            rulesList.add(rules);
        }
        res.setRules(rulesList);
        map.put("result", new Result(200, "获取数据成功"));
        map.put("data", res);
        return map;
    }

    @Override
    public List<Num> getNumByParId(int parId) {
        return numDao.findAllByPartitionIdAndEnabledOrderBySortDesc(parId, true);
    }

    @Override
    public NumDetailsRes getNumDetails(int id) {
        Num num = numDao.findOne(id);
        NumDetailsRes res= new NumDetailsRes();
        if (num!=null){
            Order order = orderDao.findByNumIdAndStatusFinish(num.getId(), false);
            NumTransaction transaction = transactionDao.findByNumIdAndStatus(num.getId(), false);
            NumTransaction nowTransaction=null;
            if (transaction!=null){
                int min = TimeUtils.getMinTimeDifference(transaction.getBeginTime().toString(), new Date().toString());
                int hour=min / 60;
                int minute=min % 60;
                transaction.setInTime(hour+"小时"+minute+"分钟");
                nowTransaction=transactionDao.save(transaction);
            }
            if (order!=null ){
                NumDetailsRes.OrderRes  orderRes= new NumDetailsRes.OrderRes();
                orderRes.setAmount(order.getAmount());
                orderRes.setOrderId(order.getId());
                List<NumDetailsRes.OrderRes.OrderItemRes> itemRes = new ArrayList<>();
                for (OrderItem item:order.getItems()){
                    NumDetailsRes.OrderRes.OrderItemRes orderItemRes = new NumDetailsRes.OrderRes.OrderItemRes();
                    orderItemRes.setAddTime(item.getAddTime());
                    orderItemRes.setAmount(item.getDealPrice());
                    orderItemRes.setCount(item.getQuantity());
                    orderItemRes.setEmpName(item.getCreateName());
                    orderItemRes.setProductName(item.getProductName());
                    if (null!=item.getProductId()){
                        orderItemRes.setProductId(item.getProductId());
                    }else {
                        orderItemRes.setSetMealId(item.getSetMealId());
                    }
                    itemRes.add(orderItemRes);
                }
                orderRes.setItemRes(itemRes);
                res.setRes(orderRes);
            }
            if (nowTransaction!=null){
                res.setNumTrans(nowTransaction);
            }
        }
        return res;
    }

    @Override
    public void mergeTran(OpenNumReq req) {
        NumTransaction transaction = transactionDao.findByNumIdAndStatus(req.getNumId(), false);
        if (transaction!=null){
            transaction.setEmpId(req.getEmpId());
            transaction.setEmpName(req.getEmpName());
            transaction.setPeople(req.getPeople());
            transaction.setNotice(req.getNotice());
        }
        transactionDao.save(transaction);
    }

    public double getBillRuleAmount(OpenNumReq req, String nowTime, String endTime) {
        BillRule billRule = billRuleDao.findOne(req.getRuleId());
        //获取开台时间 以及现在的时间差  是分钟
        int difference = TimeUtils.getMinTimeDifference(nowTime, endTime);
        double amount = 0.0;
        long dValus;
        long eValus;
        if (difference - billRule.getBeginOrderTime() < 0) {
            amount = billRule.getBeginOrderTime();
        }
        //按小时计费
        if (difference - billRule.getBeginOrderTime() >= 0) {
            //按小时计费
            if (billRule.isHourEnabled()) {
                //是否是按真实时间计费
                if (billRule.isActualEnabled()) {
                    //获取按小时计费的金额
                    double oneMinAmount = TimeUtils.getOneMinAmount(60, billRule.getOneHourAmount());
                    amount = difference * oneMinAmount;
                } else {
                    //得到总的多少分钟
                    eValus = difference;
                    //得到多少个小时
                    dValus = (difference / 60);
                    //计算这个小时内的金额
                    amount = dValus * billRule.getOneHourAmount();
                    //得到多少分钟
                    long i = eValus % 60;
                    int judge = TimeUtils.compareTime(billRule.getSectionFrom(), i, billRule.getSectionTo());
                    if (judge == 1) {
                        //计算第一个区间的时间费
                        //计算每分钟多少钱
                        double oneMinAmount = TimeUtils.getOneMinAmount(60, billRule.getOneHourAmount());
                        amount += (billRule.getSectionTo() * oneMinAmount);
                    } else if (judge == 2) {
                        amount += billRule.getOneHourAmount();
                    }
                }
            } else {
                if (billRule.isActualEnabled()) {
                    //得到多少个小时
                    dValus = (difference / 60);
                    int j = TimeUtils.compareHourTime(billRule.getRegionTime(), dValus);
                    if (j == 1) {
                        amount = billRule.getRegionAmount();
                    } else if (j == 2) {
                        //得到总时间  单位分钟
                        eValus = difference;
                        //得到总共多少个小时
                        dValus = (difference / 60);
                        //计算  区间段的 每小时多少钱
                        double oneHourAmount = TimeUtils.getOneMinAmount(billRule.getRegionTime(), billRule.getRegionAmount());
                        //得到总的整段时间的金额
                        amount = billRule.getRegionAmount() + ((dValus - billRule.getRegionTime()) * oneHourAmount);
                        //得到多少分钟
                        long i = eValus % 60;
                        //计算每分钟多少钱
                        double oneMinAmount = TimeUtils.getOneMinAmount(60, oneHourAmount);
                        amount += i * oneMinAmount;
                    }

                } else {
                    dValus = (difference / 60);
                    int j = TimeUtils.compareHourTime(billRule.getRegionTime(), dValus);
                    if (j == 1) {
                        amount = billRule.getRegionAmount();
                    } else if (j == 2) {
                        //得到总时间  单位分钟
                        eValus = difference;
                        //得到总共多少个小时
                        dValus = (difference / 60);
                        //计算整段时间金额
                        amount = billRule.getRegionAmount() + ((dValus - billRule.getRegionTime()) * billRule.getOneHourAmount());
                        //得到多少剩余多少分钟
                        long i = eValus % 60;
                        //计算每分钟多少钱
                        int judge = TimeUtils.compareTime(billRule.getSectionFrom(), i, billRule.getSectionTo());
                        if (judge == 1) {
                            //计算每分钟多少钱
                            double oneMinAmount = TimeUtils.getOneMinAmount(60, billRule.getOneHourAmount());
                            //计算第一个区间的时间费
                            amount += (billRule.getSectionTo() * oneMinAmount);
                        } else if (judge == 2) {
                            amount += billRule.getOneHourAmount();
                        }
                    }
                }
            }
        }
        //收取服务费
        if (billRule.isServiceEnabled()) {
            //得到的是秒
            dValus = TimeUtils.getNowTime(nowTime, billRule.getServiceBegin(), billRule.getServiceEnd());
            eValus = dValus;
            //得到多少个小时
            dValus = dValus / 3600;
            //得到多少分钟
            long i = (eValus % 3600) / 60;
            amount += billRule.getServiceAmount() * dValus;
            //判断分钟在不在需求时间内
            int judge = TimeUtils.compareTime(billRule.getServiceFrom(), i, billRule.getServiceTo());
            if (judge == 1) {
                //时间区间的服务费
                amount += (billRule.getServiceTo() * (billRule.getServiceAmount() / 60));
            } else if (judge == 2) {
                //一个小时的服务费
                amount += billRule.getServiceAmount();
            }
        }
        if (amount > billRule.getUpAmount() && billRule.getUpAmount() > 0) {
            amount = billRule.getUpAmount();
        }
        return amount;
    }


}
